import tools from '../../util/tools'

let eventsAPI = function(Wine){
	/**
	 * [trigger 触发事件]
	 * @return {[type]} [description]
	 */
	Wine.prototype.$trigger = function(event){
		let isString = typeof event === 'string'
		event = isString ? event : event.name
		let cbs = this._events[event]
		let args = tools.toArray(arguments,1)
		if (cbs) {
			let i = 0
			let j = cbs.length
			for(;i<j;i++){
				let cb = cbs[i]
				cb.apply(this,args)
			}
		}
	}

	/**
	 * [on 注册Wine事件]
	 * @param  {[type]} event [description]
	 * @param  {[type]} fun   [description]
	 * @return {[type]}       [description]
	 */
	Wine.prototype.$on = function(event,fun){
		let cbs = this._events[event]
		cbs ? cbs.push(fun) : this._events[event] = []
		if (!cbs) {
			this._events[event].push(fun)
		}
		return this
	}

	/**
	 * [once 单例事件]
	 * @param  {[type]} event [description]
	 * @param  {[type]} fun   [description]
	 * @return {[type]}       [description]
	 */
	Wine.prototype.$once = function(event,fun){
		let self = this
		function _on(){
			//先删除_on事件
			self.$off(event,_on)
			//再执行一次原注册事件
			fun.apply(this,arguments)
		}
		_on.fun = fun
		this.$on(event,_on)
		return this
	}

	/**
	 * [off 删除事件]
	 * @param  {[type]} event [description]
	 * @param  {[type]} fun   [description]
	 * @return {[type]}       [description]
	 */
	Wine.prototype.$off = function(event,fun){
		let cbs = this._events[event]

		//事件列队中无事件
		if (!cbs) {
			return this
		}

		//删除所有的事件
		if (!event && !fun) {
			this._events = {}
			return this;
		}

		//只有事件名称时
		if (event && !fun) {
			this._events[event] = null
			return this
		}

		//删除某个事件队列中的某个事件
		let cb;
		let i = cbs.length
		while(i--){
			cb = cbs[i]
			if (cb === fun || cb.fun === fun) {
				cbs.splice(i,1)
				break
			}
		}
		return this
	}

	/**
	 * [broadcast 将所有字节点的事件皆触发]
	 * @param  {[type]} event [description]
	 * @return {[type]}       [description]
	 */
	Wine.prototype.$broadcast = function(event){
		let isString = typeof event === 'string'
		event = isString ? event : event.name
		let children = this.$children
		let i = 0
		let j = children.length
		let args = tools.toArray(arguments,1)
		for(;i<j;i++){
			let child = children[i]
			child.$trigger.apply(child,args)
			child.$broadcast.apply(child,args)
		}
		return this
	}

	/**
	 * [dispatch 将所有父节点的事件皆触发]
	 * @param  {[type]} event [description]
	 * @return {[type]}       [description]
	 */
	Wine.prototype.$dispatch = function(event){
		let isString = typeof event === 'string'
		event = isString ? event : event.name
		let parent = this.$parent
		let args = tools.toArray(arguments,1)
		while(parent){
			parent.$trigger.apply(parent,args)
			parent = parent.$parent
		}
	}
}
module.exports = eventsAPI